//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package admin_roadmap_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/roadmap_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/admin_auth_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *RoadmapAdminApiImpl) Create(ctx context.Context, req *roadmap_api.AdminCreateRequest) (*roadmap_api.AdminCreateResponse, error) {
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminCreateResponse{
			Code:   roadmap_api.AdminCreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminCreateResponse{
			Code:   roadmap_api.AdminCreateResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.Create {
		return &roadmap_api.AdminCreateResponse{
			Code:   roadmap_api.AdminCreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	roadmapId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		dbItem := &roadmap_dao.RoadmapInfoDbItem{
			RoadmapId: roadmapId,
			BasicInfo: roadmap_dao.BasicRoadmapInfoDbItem{
				Title: req.BasicInfo.Title,
				Desc:  req.BasicInfo.Desc,
			},
			OwnerType:   uint32(roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN),
			PubState:    false,
			HotValue:    0,
			TagList:     []string{},
			OwnerUserId: adminSess.UserName,
			CreateTime:  nowTime,
			UpdateTime:  nowTime,
		}
		err = roadmap_dao.RoadmapInfoDao.Insert(sessCtx, dbItem)
		if err != nil {
			return nil, err
		}
		return &roadmap_api.AdminCreateResponse{
			Code:      roadmap_api.AdminCreateResponse_CODE_OK,
			RoadmapId: roadmapId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_api.AdminCreateResponse), nil
}

func (apiImpl *RoadmapAdminApiImpl) List(ctx context.Context, req *roadmap_api.AdminListRequest) (*roadmap_api.AdminListResponse, error) {
	emptyList := []*roadmap_api.RoadmapInfo{}

	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminListResponse{
			Code:        roadmap_api.AdminListResponse_CODE_WRONG_SESSION,
			ErrMsg:      "会话不存在",
			RoadmapList: emptyList,
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminListResponse{
			Code:        roadmap_api.AdminListResponse_CODE_NOT_AUTH,
			ErrMsg:      "未授权会话",
			RoadmapList: emptyList,
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.Read {
		return &roadmap_api.AdminListResponse{
			Code:        roadmap_api.AdminListResponse_CODE_NO_PERMISSION,
			ErrMsg:      "没有权限",
			RoadmapList: emptyList,
		}, nil
	}

	count, err := roadmap_dao.RoadmapInfoDao.Count(ctx, req.ListParam, req.FilterByPubState, req.PubState)
	if err != nil {
		return nil, err
	}
	roadmapItemList, err := roadmap_dao.RoadmapInfoDao.List(ctx, req.ListParam, req.FilterByPubState, req.PubState, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userIdList := []string{}
	for _, roadmapItem := range roadmapItemList {
		if roadmapItem.OwnerType == uint32(roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER) {
			userIdList = append(userIdList, roadmapItem.OwnerUserId)
		}
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	infoList := []*roadmap_api.RoadmapInfo{}
	for _, roadmapItem := range roadmapItemList {
		userPerm := apiImpl.calcUserPerm(roadmapItem, adminSess.UserName, adminUserCfg.PermInfo.RoadmapPerm)
		info := roadmapItem.ToRoadmapInfo(userPerm)
		if roadmapItem.OwnerType == uint32(roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN) {
			info.OwnerDisplayName = info.OwnerUserId
		} else {
			userItem, ok := userItemMap[roadmapItem.OwnerUserId]
			if ok {
				info.OwnerDisplayName = userItem.BasicInfo.DisplayName
				info.OwnerLogoUri = userItem.BasicInfo.LogoUri
			}
		}
		infoList = append(infoList, info)
	}

	return &roadmap_api.AdminListResponse{
		Code:        roadmap_api.AdminListResponse_CODE_OK,
		TotalCount:  count,
		RoadmapList: infoList,
	}, nil
}

func (apiImpl *RoadmapAdminApiImpl) Get(ctx context.Context, req *roadmap_api.AdminGetRequest) (*roadmap_api.AdminGetResponse, error) {
	emptyInfo := &roadmap_api.RoadmapInfo{
		BasicInfo: &roadmap_api.BasicRoadmapInfo{},
	}
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminGetResponse{
			Code:    roadmap_api.AdminGetResponse_CODE_WRONG_SESSION,
			ErrMsg:  "会话不存在",
			Roadmap: emptyInfo,
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminGetResponse{
			Code:    roadmap_api.AdminGetResponse_CODE_NOT_AUTH,
			ErrMsg:  "未授权会话",
			Roadmap: emptyInfo,
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.Read {
		return &roadmap_api.AdminGetResponse{
			Code:    roadmap_api.AdminGetResponse_CODE_NO_PERMISSION,
			ErrMsg:  "没有权限",
			Roadmap: emptyInfo,
		}, nil
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_api.AdminGetResponse{
			Code:    roadmap_api.AdminGetResponse_CODE_NO_ROADMAP,
			ErrMsg:  "路线图不存在",
			Roadmap: emptyInfo,
		}, nil
	}

	//获取用户信息
	userIdList := []string{}
	if roadmapItem.OwnerType == uint32(roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER) {
		userIdList = append(userIdList, roadmapItem.OwnerUserId)
	}

	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	userPerm := apiImpl.calcUserPerm(roadmapItem, adminSess.UserName, adminUserCfg.PermInfo.RoadmapPerm)
	info := roadmapItem.ToRoadmapInfo(userPerm)
	if roadmapItem.OwnerType == uint32(roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN) {
		info.OwnerDisplayName = info.OwnerUserId
	} else {
		userItem, ok := userItemMap[roadmapItem.OwnerUserId]
		if ok {
			info.OwnerDisplayName = userItem.BasicInfo.DisplayName
			info.OwnerLogoUri = userItem.BasicInfo.LogoUri
		}
	}
	return &roadmap_api.AdminGetResponse{
		Code:    roadmap_api.AdminGetResponse_CODE_OK,
		Roadmap: info,
	}, nil
}

func (apiImpl *RoadmapAdminApiImpl) Update(ctx context.Context, req *roadmap_api.AdminUpdateRequest) (*roadmap_api.AdminUpdateResponse, error) {
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminUpdateResponse{
			Code:   roadmap_api.AdminUpdateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminUpdateResponse{
			Code:   roadmap_api.AdminUpdateResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.UpdateContent {
		return &roadmap_api.AdminUpdateResponse{
			Code:   roadmap_api.AdminUpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_api.AdminUpdateResponse{
			Code:   roadmap_api.AdminUpdateResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(roadmapItem, adminSess.UserName, adminUserCfg.PermInfo.RoadmapPerm)
	if !userPerm.CanUpdateContent {
		return &roadmap_api.AdminUpdateResponse{
			Code:   roadmap_api.AdminUpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.RoadmapInfoDao.UpdateBasicInfo(sessCtx, req.RoadmapId, &roadmap_dao.BasicRoadmapInfoDbItem{
			Title: req.BasicInfo.Title,
			Desc:  req.BasicInfo.Desc,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &roadmap_api.AdminUpdateResponse{
			Code: roadmap_api.AdminUpdateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_api.AdminUpdateResponse), nil
}

func (apiImpl *RoadmapAdminApiImpl) UpdateTag(ctx context.Context, req *roadmap_api.AdminUpdateTagRequest) (*roadmap_api.AdminUpdateTagResponse, error) {
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminUpdateTagResponse{
			Code:   roadmap_api.AdminUpdateTagResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminUpdateTagResponse{
			Code:   roadmap_api.AdminUpdateTagResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.UpdateTag {
		return &roadmap_api.AdminUpdateTagResponse{
			Code:   roadmap_api.AdminUpdateTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := roadmap_dao.RoadmapInfoDao.Exist(ctx, req.RoadmapId, false, false)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_api.AdminUpdateTagResponse{
			Code:   roadmap_api.AdminUpdateTagResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.RoadmapInfoDao.UpdateTagList(sessCtx, req.RoadmapId, req.TagList)
		if err != nil {
			return nil, err
		}
		return &roadmap_api.AdminUpdateTagResponse{
			Code: roadmap_api.AdminUpdateTagResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_api.AdminUpdateTagResponse), nil
}

func (apiImpl *RoadmapAdminApiImpl) UpdatePubState(ctx context.Context, req *roadmap_api.AdminUpdatePubStateRequest) (*roadmap_api.AdminUpdatePubStateResponse, error) {
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminUpdatePubStateResponse{
			Code:   roadmap_api.AdminUpdatePubStateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminUpdatePubStateResponse{
			Code:   roadmap_api.AdminUpdatePubStateResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.UpdatePubState {
		return &roadmap_api.AdminUpdatePubStateResponse{
			Code:   roadmap_api.AdminUpdatePubStateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.RoadmapInfoDao.UpdatePubState(sessCtx, req.RoadmapId, req.PubState)
		if err != nil {
			return nil, err
		}
		if !req.PubState {
			//清除用户访问记录
			err = roadmap_dao.AccessRecordDao.RemoveByRoadmap(sessCtx, req.RoadmapId)
			if err != nil {
				return nil, err
			}
		}
		return &roadmap_api.AdminUpdatePubStateResponse{
			Code: roadmap_api.AdminUpdatePubStateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_api.AdminUpdatePubStateResponse), nil
}

func (apiImpl *RoadmapAdminApiImpl) Remove(ctx context.Context, req *roadmap_api.AdminRemoveRequest) (*roadmap_api.AdminRemoveResponse, error) {
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminRemoveResponse{
			Code:   roadmap_api.AdminRemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminRemoveResponse{
			Code:   roadmap_api.AdminRemoveResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.Remove {
		return &roadmap_api.AdminRemoveResponse{
			Code:   roadmap_api.AdminRemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_api.AdminRemoveResponse{
			Code: roadmap_api.AdminRemoveResponse_CODE_OK,
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(roadmapItem, adminSess.UserName, adminUserCfg.PermInfo.RoadmapPerm)
	if !userPerm.CanRemove {
		return &roadmap_api.AdminRemoveResponse{
			Code:   roadmap_api.AdminRemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.RoadmapInfoDao.Remove(sessCtx, req.RoadmapId)
		if err != nil {
			return nil, err
		}
		err = roadmap_dao.NodeDao.RemoveByRoadmap(sessCtx, req.RoadmapId)
		if err != nil {
			return nil, err
		}
		err = roadmap_dao.EdgeDao.RemoveByRoadmap(sessCtx, req.RoadmapId)
		if err != nil {
			return nil, err
		}
		//清除用户访问记录
		err = roadmap_dao.AccessRecordDao.RemoveByRoadmap(sessCtx, req.RoadmapId)
		if err != nil {
			return nil, err
		}
		//清除节点状态
		err = roadmap_dao.StateDao.RemoveByRoadmap(sessCtx, req.RoadmapId)
		if err != nil {
			return nil, err
		}
		return &roadmap_api.AdminRemoveResponse{
			Code: roadmap_api.AdminRemoveResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_api.AdminRemoveResponse), nil
}

func (apiImpl *RoadmapAdminApiImpl) ChangeOwnerUser(ctx context.Context, req *roadmap_api.AdminChangeOwnerUserRequest) (*roadmap_api.AdminChangeOwnerUserResponse, error) {
	adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
	if !ok {
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code:   roadmap_api.AdminChangeOwnerUserResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	if !adminSess.AuthOk {
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code:   roadmap_api.AdminChangeOwnerUserResponse_CODE_NOT_AUTH,
			ErrMsg: "未授权会话",
		}, nil
	}
	adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
	if err != nil {
		return nil, err
	}
	if !adminUserCfg.PermInfo.RoadmapPerm.ChangeOwner {
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code:   roadmap_api.AdminChangeOwnerUserResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查路线图是否存在
	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code:   roadmap_api.AdminChangeOwnerUserResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
		}, nil
	}
	if roadmapItem.OwnerType != uint32(roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN) {
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code:   roadmap_api.AdminChangeOwnerUserResponse_CODE_NO_PERMISSION,
			ErrMsg: "只能修改官方路线图",
		}, nil
	}
	//检查目标用户是否存在
	exist, err := dao.AdminUserDao.Exist(ctx, req.TargetUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code:   roadmap_api.AdminChangeOwnerUserResponse_CODE_NO_TARGET_USER,
			ErrMsg: "目标用户不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.RoadmapInfoDao.UpdateOwnerUser(sessCtx, req.RoadmapId, req.TargetUserId)
		if err != nil {
			return nil, err
		}
		return &roadmap_api.AdminChangeOwnerUserResponse{
			Code: roadmap_api.AdminChangeOwnerUserResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_api.AdminChangeOwnerUserResponse), nil
}

func (apiImpl *RoadmapAdminApiImpl) calcUserPerm(roadmapItem *roadmap_dao.RoadmapInfoDbItem, ownerUserId string, roadmapPerm *admin_auth_api.RoadmapPerm) *roadmap_api.UserPerm {
	userPerm := &roadmap_api.UserPerm{}
	if roadmapPerm.UpdateContent && ownerUserId == roadmapItem.OwnerUserId {
		userPerm.CanUpdateContent = true
	}
	if roadmapPerm.UpdatePubState {
		userPerm.CanUpdatePubState = true
	}
	if roadmapPerm.Remove {
		userPerm.CanRemove = true
	}

	if roadmapItem.PubState {
		userPerm.CanRemove = false
	}
	return userPerm
}
